#include <misclib.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <stdarg.h>
#include "unitTester.hpp"

static vector< xCPPUnitTester* > & getCPPUnitTests() {
	static vector< xCPPUnitTester * > cppUnitTests;
	return cppUnitTests;
}
// =================================================================================== //
using namespace std;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -	
xCPPUnitTester::xCPPUnitTester(const char * tName) : testName(tName), testPassed(false) 
{
	/* Register tests */ 
	vector< xCPPUnitTester * > cppUnitTests = getCPPUnitTests();
	cppUnitTests.push_back(this);
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -	
bool xCPPUnitTester::testFailed() const {
	return ! testPassed;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -	
const string & xCPPUnitTester::name() const {
	return testName;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -	
void xCPPUnitTester::testAssert( bool cond, const char * errorMsgFmt, ... ) {
	va_list args;
	va_start(args, errorMsgFmt);
	string errorMsg;
	stdvsprintf( errorMsg, errorMsgFmt, args );
	errors.push_back( errorMsg );
	testPassed = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -	
void xCPPUnitTester::displayStatus() const {
	printf("\t-------------------------------------------------------------\n");
	if( testPassed ){
		printf("\tTest '%s' PASSED!!\n", testName.c_str());
	}else{
		printf("\tTest '%s' FAILED for the following reasons:\n", testName.c_str());
	}
	for(size_t i = 0; i < errors.size(); i++){
		printf("\t *) %s.\n", errors[i].c_str());
	}
	printf("\t-------------------------------------------------------------\n");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
xCPPUnitTester::~xCPPUnitTester() {
	displayStatus();
}	
// =================================================================================== //
bool RunCPPUnitTests()
{
	printf("================================================================\n");
	printf("Beginning CPP Unit Tests\n");
	printf("================================================================\n");
	vector<xCPPUnitTester*> & cppUnitTests = getCPPUnitTests();
	vector<string> failedTests;
	for(size_t i = 0; i < cppUnitTests.size(); i++){
		xCPPUnitTester * unitTest = cppUnitTests[i];
		unitTest->runTest();
		if( unitTest->testFailed() ) failedTests.push_back( unitTest->name() );
		delete (cppUnitTests[i]); // this should invoke the status of the test 
		cppUnitTests[i] = NULL;
	}
	cppUnitTests.clear();
	printf("================================================================\n");
	printf("Finished running CPP Unit Tests\n");
	printf("================================================================\n");
	printf("Summary:\n");
	printf("\t %i Tests Failed\n", (int) failedTests.size());
	for(size_t i = 0; i < failedTests.size(); i++){
		printf("\t   %s test Failed.\n", failedTests[i].c_str());
	}
	printf("================================================================\n");
	return failedTests.size() == 0;
}

